package com.aloha.springframework.beans.factory.annotation;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.TypeUtil;
import com.aloha.springframework.beans.BeansException;
import com.aloha.springframework.beans.PropertyValues;
import com.aloha.springframework.beans.factory.BeanFactory;
import com.aloha.springframework.beans.factory.BeanFactoryAware;
import com.aloha.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.aloha.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import com.aloha.springframework.core.convert.ConversionService;

import java.lang.reflect.Field;

/**
 * @author DaiZhiHeng
 * @description 用于在创建对象后在给实例数据填充数据前
 * @date 2023/7/7 16:37
 */
public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

    private ConfigurableListableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        Class<?> beanClass = bean.getClass();
        Field[] fields = beanClass.getDeclaredFields();
        // 处理 @Value
        for (Field field : fields) {
            Value annotation = field.getAnnotation(Value.class);
            if (annotation == null) continue;
            Object value = annotation.value();
            value = beanFactory.resolveEmbeddedValue((String) value);
            //类型转换
            Class<?> sourceType = value.getClass();
            Class<?> targetType = (Class<?>) TypeUtil.getType(field);
            ConversionService conversionService = beanFactory.getConversionService();
            if (conversionService != null) {
                if (conversionService.canConvert(sourceType, targetType)) {
                    value = conversionService.convert(value, targetType);
                }
            }
            BeanUtil.setFieldValue(bean, field.getName(), value);
        }
        // 处理 @Autowired
        for (Field field : fields) {
            Autowired autowiredAnnotation = field.getAnnotation(Autowired.class);
            if (autowiredAnnotation == null) continue;
            Class<?> fieldType = field.getType();
            String dependBeanName;
            Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class);
            Object dependBean;
            if (qualifierAnnotation != null) {
                dependBeanName = qualifierAnnotation.value();
                dependBean = beanFactory.getBean(dependBeanName, fieldType);
            } else {
                dependBean = beanFactory.getBean(fieldType);
            }
            BeanUtil.setFieldValue(bean, field.getName(), dependBean);
        }
        return pvs;
    }
}
